from dataclasses import dataclass
from dataclasses_json import dataclass_json
from SkyOfficeLint.models import *
from MelodieFuncFlow import MelodieFrozenGenerator
from typing import List, Literal
from .checker_reports import CheckerReports, CheckerReport


# @dataclass_json
# @dataclass
# class CheckerReport:
#     type: Literal["warning", "error"]
#     description: str


class CheckerConfig:
    def __init__(self) -> None:
        self.indentation_unit: Literal["char", "pt"] = "char"
        self.allowed_fonts: List[str] = {
            item.lower() for item in ["Times New Roman", "宋体"]
        }


class BaseChecker:
    def __init__(self, document: DocumentInfo) -> None:
        self.document = document
        self.config = CheckerConfig()

    def run(self):
        pass


class ParagraphsChecker(BaseChecker):
    def first_line_indent_by_whitespaces_checker(
        self, paragraph: ParagraphInfo
    ) -> CheckerReport:
        """检测是否使用制表符/空格来代替首行缩进"""
        if paragraph.text.startswith(" "):
            return CheckerReports.ParagraphFormatError.Indentation.INDENT_FIRST_LINE_WITH_SPACE(
                paragraph
            )
        elif paragraph.text.startswith("\t"):
            return CheckerReports.ParagraphFormatError.Indentation.INDENT_FIRST_LINE_WITH_TAB(
                paragraph
            )

    def check_indentation_units(self, paragraph: ParagraphInfo) -> CheckerReport:
        """检测缩进的单位是否为厘米"""
        special_indentation = paragraph.indentations.special
        unit_trans = lambda u: {"char": "字符", "pt": "磅"}[u]
        if (
            special_indentation is not None
            and special_indentation.value is not None
            and special_indentation.value.type != self.config.indentation_unit
        ):
            return (
                CheckerReports.ParagraphFormatError.Indentation.INDENT_UNIT_NOT_MATCH(
                    paragraph,
                    unit_trans(special_indentation.value.type),
                    unit_trans(self.config.indentation_unit),
                )
            )

    def check_invalid_fonts(self, paragraph: ParagraphInfo) -> CheckerReport:
        """检查不合规的字体"""
        invalid_fonts = (
            MelodieFrozenGenerator(paragraph.font)
            .filter(lambda font: font.name.lower() not in self.config.allowed_fonts)
            .map(lambda font: font.name)
            .s
        )
        if len(invalid_fonts) > 0:
            return CheckerReports.ParagraphFormatError.Font.INVALID_FONT(
                paragraph, "、".join(invalid_fonts)
            )

    def check_paragraph_format(
        self, section: SectionInfo, paragraph: ParagraphInfo
    ) -> CheckerReport:
        return (
            MelodieFrozenGenerator(
                [
                    self.first_line_indent_by_whitespaces_checker,
                    self.check_indentation_units,
                    self.check_invalid_fonts,
                ]
            )
            .map(lambda func: func(paragraph))
            .filter(lambda item: item is not None)
            .l
        )

    def run(self) -> List[CheckerReport]:
        return (
            self.document.iter_paragraphs()
            .star_map(self.check_paragraph_format)
            .reduce(lambda a, b: a + b, [])
        )
